package com.lxb.educenter.controller;

import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.lxb.commonutils.JwtUtils;
import com.lxb.educenter.entity.UcenterMember;
import com.lxb.educenter.service.UcenterMemberService;
import com.lxb.educenter.utils.ConstantWxUtils;
import com.lxb.educenter.utils.HttpClientUtils;
import com.lxb.servicebase.exceptionhandler.GuliException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;

/**
 * 微信扫码登录
 *
 * @author xuebin.li
 * @createTime 2022/12/30 13:43
 */
@Api(description = "微信扫码登录")
@Controller //注意这里没有配置 @RestController
//@CrossOrigin
@RequestMapping("/api/ucenter/wx")
public class WxApiController {

    @Autowired
    private UcenterMemberService service;


    @ApiOperation("信息返回接口,获取扫码信息")
    @GetMapping("/callback")
    public String callback(String code, String state) {

        try {
            String headimgurl = ""; //nickname普通用户昵称
            String nickname = ""; //headimgurl 用户头像
            String jwtToken = ""; //token

            //1.得到授权临时票据code
            System.out.println(code);
            System.out.println(state);
            //TODO 从redis中将state获取出来，和当前传入的state作比较
            //如果一致则放行，如果不一致则抛出异常：非法访问
            //2. 向认证服务器发送请求换取access_token
            String baseAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token" +
                    "?appid=%s" +
                    "&secret=%s" +
                    "&code=%s" +
                    "&grant_type=authorization_code";

            //拼接三个参数：id 秘钥 code
            String accessTokenUrl = String.format(baseAccessTokenUrl,
                    ConstantWxUtils.WX_APP_ID,
                    ConstantWxUtils.WX_APP_SECRET,
                    code);

            //请求上面拼接好的地址，得到两个值 access_token 和 openid
            //使用httpclient【不用浏览器，也能模拟器出浏览器的请求和响应过程】发送请求，得到返回的结果
            String accessTokenInfo = null;
            try {
                accessTokenInfo = HttpClientUtils.get(accessTokenUrl);
                System.out.println("accessTokenInfo：。。。" + accessTokenInfo);
            } catch (Exception e) {
                throw new GuliException(20001, "获取access_token失败");
            }

            //解析字符串
            Gson gson = new Gson();
            HashMap map = gson.fromJson(accessTokenInfo, HashMap.class);
            //3.获取access_token 接口调用凭证和 openid 授权用户唯一标识
            String access_token = (String) map.get("access_token");
            String openid = (String) map.get("openid");


            //4.获取用户个人信息
            //拿着 access_token 和 openid 的值再去请求微信提供的固定地址
            //访问微信的资源服务器，获取用户信息
            String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +
                    "?access_token=%s" +
                    "&openid=%s";
            String userInfoUrl = String.format(
                    baseUserInfoUrl,
                    access_token,
                    openid);

            String resultUserInfo = null;
            try {
                resultUserInfo = HttpClientUtils.get(userInfoUrl);
                System.out.println("resultUserInfo:" + resultUserInfo);
            } catch (Exception e) {
                throw new GuliException(20001, "获取用户信息失败");
            }

            HashMap hashMap = gson.fromJson(resultUserInfo, HashMap.class);

            //获取返回的 nickname普通用户昵称 和 headimgurl 用户头像
            nickname = (String) hashMap.get("nickname");
            headimgurl = (String) hashMap.get("headimgurl");

            //5.判断该扫码人，是否有注册
            UcenterMember member = service.getByOpenid(openid);
            if (member == null) {

                System.out.println("新用户注册");

                if (StringUtils.isNotEmpty(nickname) || StringUtils.isNotEmpty(headimgurl)) {
                    member = new UcenterMember();
                    //新增微信新用户
                    member.setOpenid(openid);
                    member.setNickname(nickname);
                    member.setAvatar(headimgurl);
                    service.save(member);
                }

                //使用JWT根据member对象生成token字符串
                jwtToken = JwtUtils.getJwtToken(member.getId(), member.getNickname());

            } else {
                System.out.println("更新用户信息");

                UcenterMember member1 = new UcenterMember();
                //已注册的用户是否需要更新数据  如：头像 微信名
                if (!nickname.equals(member1.getNickname()) || !headimgurl.equals(member1.getAvatar())) {
                    //更新微信用户信息
                    member1.setId(member.getId());
                    member1.setNickname(nickname);
                    member1.setAvatar(headimgurl);
                    service.updateById(member1);
                }

                //使用JWT根据member对象生成token字符串
                jwtToken = JwtUtils.getJwtToken(member1.getId(), member1.getNickname());
            }


            //扫码登录后，跳转回前端首页，通过路径传递token字符串
            return "redirect:http://localhost:3000?token=" + jwtToken;
        } catch (Exception e) {
            throw new GuliException(20001, "登录异常");
        }
    }


    @ApiOperation(value = "微信登录接口,生成二维码")
    @GetMapping("/login")
    public String login() {

        //1.微信开放平台授权baseUrl
        String baseUrl = "https://open.weixin.qq.com/connect/qrconnect" +
                "?appid=%s" +
                "&redirect_uri=%s" +
                "&response_type=code" +
                "&scope=snsapi_login" +
                "&state=%s" +
                "#wechat_redirect";

        //回调地址
        String redirectUrl = ConstantWxUtils.WX_REDIRECT_URL; //获取业务服务器重定向地址
        //2.使用urlEncode对链接进行处理
        try {
            redirectUrl = URLEncoder.encode(redirectUrl, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new GuliException(20001, e.getMessage());
        }

        // 防止csrf攻击（跨站请求伪造攻击）
        //String state = UUID.randomUUID().toString().replaceAll("-", "");//一般情况下会使用一个随机数
        String state = "imhelen";//为了让大家能够使用我搭建的外网的微信回调跳转服务器，这里填写你在ngrok的前置域名
        System.out.println("state = " + state);
        // 采用redis等进行缓存state 使用sessionId为key 30分钟后过期，可配置
        //键："wechar-open-state-" + httpServletRequest.getSession().getId()
        //值：satte
        //过期时间：30分钟

        //3.生成rqCodeUrl
        String rqCodeUrl = String.format(baseUrl,
                ConstantWxUtils.WX_APP_ID,
                redirectUrl,
                state);

        return "redirect:" + rqCodeUrl;
    }

}
